/*
 * bootsecto.c
 *
 *  Created on: 21/10/2011
 *      Author: Pablo Arias & Juan Pablo De Blas
 */

#include "bootsecto.h"
#include "conexiones.h"
#include "nipc.h"
#include "utils.h"
#include <sys/mman.h>


extern 		t_conexion *conexiones;
extern 		char fat_table_array[524288];

unsigned int getFatSize(char *bootSector){
	char aux[4] = {bootSector[0x24],bootSector[0x25],bootSector[0x26],bootSector[0x27]};
	return toLilEndian(aux,4);
}

unsigned int getReservedSectors(char *bootSector){
	char aux[2] = {bootSector[0xE],bootSector[0xF]};
	return toLilEndian(aux,2);
}

char getSectorPerCluster(char *bootSector){
	char aux[1] = {bootSector[0xD]};
	return toLilEndian(aux,1);
}

char getNumberOfFat(char *bootSector){
	char aux[1] = {bootSector[0x10]};
	return toLilEndian(aux,1);
}

unsigned int getRootCluster(char *bootSector){
	char aux[4] = {bootSector[0x2C],bootSector[0x2D],bootSector[0x2E],bootSector[0x2F]};
	return toLilEndian(aux,4);
}

unsigned int getSectorClusterN(unsigned int n,bootSector boot){
	unsigned int addrs = (n- boot.rootCluster) *boot.sectorPerCluster + boot.reservedSectors + (boot.fatCant*boot.fatSize);
	return addrs;
}


bootSector getBootSector(char disk){
	bootSector boot;
	char *map;
	map = mmap(0,1,PROT_READ ,MAP_PRIVATE, disk, 0);
	boot.reservedSectors = getReservedSectors(map);
	boot.fatSize = getFatSize(map);
	boot.fatCant = getNumberOfFat(map);
	boot.sectorPerCluster = getSectorPerCluster(map);
	boot.rootCluster = getRootCluster(map);
	return boot;
}


bootSector getBootSectorSocket(){
	bootSector bootSec;
	nipcMessage msg;
	char *buffer;
	int i;

	while(conexiones[i].libre != FREE)
	i++;

	conexiones[i].libre = BUSY;

	sprintf(msg.payloadID, "%d",conexiones[i].socket);
	msg.type = 1;
	msg.payload = "0;";

	nipc_send(&msg, conexiones[i].socket);
	nipc_recv(&msg, conexiones[i].socket);

	conexiones[i].libre = FREE;

	buffer = strtok(msg.payload, "\0");

	bootSec.reservedSectors = getReservedSectors(buffer);
	bootSec.fatSize = getFatSize(buffer);
	bootSec.fatCant = getNumberOfFat(buffer);
	bootSec.sectorPerCluster = getSectorPerCluster(buffer);
	bootSec.rootCluster = getRootCluster(buffer);

	return bootSec;
}

Nodo *getFreeClusters(char disk){
	int *map;
	Nodo *free = NULL;
	int i;

	map = mmap(0,1,PROT_READ ,MAP_PRIVATE, disk, 0x4000);

	for(i = 2; i < 1026; i++){
		if(map[i] == 0){
		add_int(&free,i);
		}
	}
	return free;
}


/*
int *getFatTable(char disk){
	char *fat_table;


		fat_table = mmap(0,1,PROT_READ|PROT_WRITE ,MAP_PRIVATE, disk,0x4000);

		return fat_table;
}
*/

void getFatTable(char*fat){

	bootSector boot; //extern bootSector bootSec (global)

    unsigned int cont = 0;
    int *p;
	int i,j;
    char *aux;

    for (i = 0; i < boot.fatSize ;i++)
    {
    	aux = getSector(boot.reservedSectors + i);

    	for(j=0; j < 512;j++)
    	{
    		fat[cont] = aux[j];
    		cont++;
    	}

    }
}

//remueve todos los clusters, pone las entradas en libre en la fat
void removeCluster(unsigned int firstCluster){

	unsigned int sig ,aux;
	int *fatTable;
	fatTable = (int*)fat_table_array;
	aux = fatTable[firstCluster];

	if(fatTable[firstCluster] == 268435455){
		fatTable[firstCluster] = 0;
		puts("el nodo fue removido");
	}



	else{
		while(aux != 268435455){

				sig = fatTable[aux];
				fatTable[aux] = 0;
				aux = sig;
		}
	}
}

//devuelve un cluster libre (su direccion) y lo pone en FAT

int getFreeCluster(disk){
	int *fat_table,i=0;
	fat_table =(int*)fat_table_array;
	i=2; //rootCluster
	while (fat_table[i] != 0){
		i++;
	}
	fat_table[i]=268435455;
	printf("lo puso en ocupado:%d\n",fat_table[i]);
	return i;
}

void addNewCluster(firstCluster,disk){
	int*fat_table,ret=0,ant=0;

	fat_table=(int*)fat_table_array;

	ret=firstCluster;

	while(ret!=268435455){
		ant=ret;
		ret = fat_table[ret];
	}
	ret=getFreeCluster(disk);
	fat_table[ant]=ret;
}
